﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Xml.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Lifestyle.Storage;
using Microsoft.Phone.Shell;
using System.IO.IsolatedStorage;

namespace KeyDoor.Searcher
{
    public partial class index : PhoneApplicationPage
    {
        private IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;

        private string postcode = "";
        private string address = "";
        private float lat;
        private float lon;

        private int bergOTD = 0;
        private int berg = 0;
        private int crimDam = 0;
        private int drug = 0;
        private int frdnForge = 0;
        private int offAgainVehi = 0;
        private int otherOff = 0;
        private int otherTheftOff = 0;
        private int robbery = 0;
        private int sexyOffences = 0;
        private int vioWI = 0;
        private int vioWOI = 0;

        private string areaID = "";
        private string adminDist = "";
        private string[] crimeResult = new string[4];

        public index()
        {
            InitializeComponent();
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                postcode = this.NavigationContext.QueryString["postcode"].ToString();
            } catch { }

            try
            {
                WebClient wClient = new WebClient();
                wClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(postcode_DownloadStringCompleted);
                wClient.DownloadStringAsync(new Uri("http://dev.virtualearth.net/REST/v1/Locations/UK/" + postcode.Replace(" ", "").ToUpper() + "?o=xml&key=" + Classes.keys.bingAPI, UriKind.Absolute));
            }
            catch
            {
                MessageBox.Show("Unable to retrieve data.", "ERROR", MessageBoxButton.OK);
                this.NavigationService.GoBack();
            }

        }

        void lifeExp_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                string jsonResult = e.Result.ToString();

                JObject lifeData = JObject.Parse(jsonResult);

                JToken results = lifeData["demographics"]["overview"];
                JToken resultsSub1 = lifeData["statistics"]["lifeexpectancy"];

                IList<lifeRating> searchResults = new List<lifeRating>();
                IList<lifeOverview> searchSub1 = new List<lifeOverview>();

                #region root
                // Set 1
                lifeRating searchResult = JsonConvert.DeserializeObject<lifeRating>(resultsSub1.ToString());
                searchResults.Add(searchResult);
                #endregion
                #region demo
                // Set 1
                lifeOverview searchResult1 = JsonConvert.DeserializeObject<lifeOverview>(results.ToString());
                searchSub1.Add(searchResult1);
                #endregion

                // Update UI
                float average = Convert.ToSingle(((Convert.ToSingle(searchResults[0].female) + Convert.ToSingle(searchResults[0].male)) / 2) % 5);
                lblMortRating.Text = average.ToString().Remove(3);

                average = Convert.ToSingle((Convert.ToSingle(searchResults[0].female) + Convert.ToSingle(searchResults[0].male)) / 2);
                satLifeExp.Text = average.ToString().Remove(4);

                lyfMale.Text = searchResults[0].male;
                lyfFemale.Text = searchResults[0].female;

                lyfLclHouse.Text = searchSub1[0].dwellings;
                lyfPop.Text = searchSub1[0].residents;

                average = 0;
                average = Convert.ToSingle(((Convert.ToSingle(lblCrimRating.Text) + Convert.ToSingle(lblMortRating.Text) + Convert.ToSingle(lblEduRating.Text)) / 3));

                lblRating.Text = average.ToString().Remove(3);

                createRecent();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can't read life expectancy data, please make sure you are connected to the internet and not behind a proxy.", "ERROR", MessageBoxButton.OK);
                this.NavigationService.GoBack();
            }
        }

        void crime_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                string[] totalCrimeLevels = e.Result.ToString().Split('^');

                bergOTD = Convert.ToInt32(totalCrimeLevels[0]);
                berg = Convert.ToInt32(totalCrimeLevels[1]);
                crimDam = Convert.ToInt32(totalCrimeLevels[2]);
                drug = Convert.ToInt32(totalCrimeLevels[3]);
                frdnForge = Convert.ToInt32(totalCrimeLevels[4]);
                offAgainVehi = Convert.ToInt32(totalCrimeLevels[5]);
                otherOff = Convert.ToInt32(totalCrimeLevels[6]);
                otherTheftOff = Convert.ToInt32(totalCrimeLevels[7]);
                robbery = Convert.ToInt32(totalCrimeLevels[8]);
                sexyOffences = Convert.ToInt32(totalCrimeLevels[9]);
                vioWI = Convert.ToInt32(totalCrimeLevels[10]);
                vioWOI = Convert.ToInt32(totalCrimeLevels[11]);

                // Update UI
                satCrimeOverview.Text = Convert.ToString(bergOTD + berg + crimDam + drug + frdnForge + offAgainVehi + otherOff + otherTheftOff + robbery
                    + sexyOffences + vioWI + vioWOI);

                crmBurgNonHse.Text = bergOTD.ToString();
                crmBurgHse.Text = berg.ToString();
                crmCrmDmg.Text = crimDam.ToString();
                crmDrug.Text = drug.ToString();
                crmFraudnForge.Text = frdnForge.ToString();
                crmOffAngVehi.Text = offAgainVehi.ToString();
                crmOthOff.Text = otherOff.ToString();
                crmRobbry.Text = robbery.ToString();
                crmSexyTiem.Text = sexyOffences.ToString();
                crmThftOff.Text = otherTheftOff.ToString();

                int average = bergOTD + berg + crimDam + drug + frdnForge + offAgainVehi + otherOff + otherTheftOff + robbery
                    + sexyOffences + vioWI + vioWOI;

                average = average % 5;

                lblCrimRating.Text = average.ToString();

                WebClient wClient = new WebClient();
                wClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(lifeExp_DownloadStringCompleted);
                wClient.DownloadStringAsync(new Uri("http://yrsareastatistics.appspot.com/?lat=" + lat + "&lon=" + lon + "&complete=true", UriKind.Absolute));
            }
            catch
            {
                MessageBox.Show("Can't read crime data, please make sure you are connected to the internet and not behind a proxy.", "ERROR", MessageBoxButton.OK);
                this.NavigationService.GoBack();
            }
        }

        void edu_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                string jsonResult = "{\"root\": " + e.Result.ToString() + "}";

                JObject educationResult = JObject.Parse(jsonResult);

                IList<JToken> results = educationResult["root"].Children()["establishment_location"].ToList();
                IList<JToken> resultsSub1 = educationResult["root"].Children()["establishment_location"]["establishment_location_metadata"].ToList();
                IList<JToken> resultsSub2 = educationResult["root"].Children()["establishment_location"]["establishment"].ToList();
                IList<JToken> resultsSub3 = educationResult["root"].Children()["establishment_location"]["establishment"]["cached_category_scores"].ToList();

                IList<educationFormat> searchResults = new List<educationFormat>();
                IList<educationFormat.establishment_location_metadata> searchResultsSub1 = new List<educationFormat.establishment_location_metadata>();
                IList<educationFormat.establishment> searchResultsSub2 = new List<educationFormat.establishment>();
                IList<educationFormat.establishment.cached_category_scores> searchResultsSub3 = new List<educationFormat.establishment.cached_category_scores>();

                #region root
                foreach (JToken result in results)
                {
                    // Set 1
                    educationFormat searchResult = JsonConvert.DeserializeObject<educationFormat>(result.ToString());
                    searchResults.Add(searchResult);
                }
                #endregion
                #region locMeta
                foreach (JToken result in resultsSub1)
                {
                    // Set 2
                    educationFormat.establishment_location_metadata searchResult = JsonConvert.DeserializeObject<educationFormat.establishment_location_metadata>(result.ToString());
                    searchResultsSub1.Add(searchResult);
                }
                #endregion
                #region estab
                foreach (JToken result in resultsSub2)
                {
                    // Set 3
                    educationFormat.establishment searchResult = JsonConvert.DeserializeObject<educationFormat.establishment>(result.ToString());
                    searchResultsSub2.Add(searchResult);
                }
                #endregion
                #region estabCache
                foreach (JToken result in resultsSub3)
                {
                    // Set 4
                    educationFormat.establishment.cached_category_scores searchResult = JsonConvert.DeserializeObject<educationFormat.establishment.cached_category_scores>(result.ToString());
                    searchResultsSub3.Add(searchResult);
                }
                #endregion

                // Save Lists to Storage
                education.mainResults = searchResults;
                education.mainResultsSub1 = searchResultsSub1;
                education.mainResultsSub2 = searchResultsSub2;
                education.mainResultsSub3 = searchResultsSub3;

                string[] highestRated = { "0", "", "" };
                float average = 0;
                int overall = 0;

                int primary = 0;
                int secondary = 0;

                int pupils = 0;

                for (int i = 0; i < searchResults.Count(); i++)
                {
                    float tempavg = 0;

                    educationFormat eduF = searchResults[i];
                    educationFormat.establishment_location_metadata eduFM = searchResultsSub1[i];
                    educationFormat.establishment eduE = searchResultsSub2[i];
                    educationFormat.establishment.cached_category_scores eduEC = searchResultsSub3[i];

                    if (eduFM.sector != null)
                    {
                        if (eduFM.sector == "primary")
                            primary++;

                        if (eduFM.sector == "secondary")
                            secondary++;
                    }

                    if (eduFM.number_of_pupils != null)
                        pupils += Convert.ToInt32(eduFM.number_of_pupils);

                    if (eduEC.exams != null || eduEC.happiness != null)
                    {
                        overall++;

                        float happ = Convert.ToSingle(eduEC.happiness);
                        float exam = Convert.ToSingle(eduEC.exams);

                        tempavg = (happ + exam) / 2;
                        average += tempavg;

                        tempavg = tempavg / 2;
                    }

                    if (Convert.ToSingle(highestRated[0]) < tempavg)
                    {
                        highestRated[0] = (tempavg + 2).ToString();
                        highestRated[1] = eduE.establishment_name + " - " + eduFM.sector;
                        highestRated[2] = eduFM.number_of_pupils.ToString();
                    }
                }

                average = (average / overall) + 2;

                // UpdateLayout UI
                eduTopRatedName.Text = highestRated[1];
                eduTopRatedNameRating.Text = highestRated[0];

                satSchoolsOverview.Text = searchResults.Count().ToString();

                if (average.ToString().Length > 3)
                    lblEduRating.Text = average.ToString().Remove(3);
                else
                    lblEduRating.Text = average.ToString();

                eduTotalPrimary.Text = primary.ToString();
                eduTotalSecondary.Text = secondary.ToString();
                eduTotalPupl.Text = pupils.ToString();
                eduTotalSch.Text = searchResults.Count().ToString();

                WebClient wClient = new WebClient();
                wClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(crime_DownloadStringCompleted);
                wClient.DownloadStringAsync(new Uri("http://xeraxic.com/projects/ext/YRS2011/govdtr.php?areaID=" + adminDist, UriKind.Absolute));
            }
            catch(Exception ex)
            {
                MessageBox.Show("Can't read education data, please make sure you are connected to the internet and not behind a proxy.", "ERROR", MessageBoxButton.OK);
                this.NavigationService.GoBack();
            }

        }

        void areaID_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                XDocument _doc = XDocument.Parse(e.Result);

                bool AID = false;
                bool ADM = false;
                int i = 0;
                int y = 0;
                foreach (XNode node in _doc.DescendantNodes())
                {
                    if (AID && i == 0)
                    {
                        areaID = node.ToString();
                        i++;
                    }

                    if (ADM && y == 2)
                    {
                        adminDist = node.ToString().Remove(4, (node.ToString().Length - 4));
                    }

                    AID = false;
                    ADM = false;

                    if (node.ToString().StartsWith("<AreaId"))
                        AID = true;
                    if (node.ToString().StartsWith("<Name"))
                    {
                        ADM = true;
                        y++;
                    }
                }

                WebClient wClient = new WebClient();
                wClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(edu_DownloadStringCompleted);
                wClient.DownloadStringAsync(new Uri("http://yrsschoolslookup.appspot.com/?lat=" + lat.ToString() + "&lon=" + lon.ToString(), UriKind.Absolute));
            }
            catch
            {
                MessageBox.Show("Can't read location data, please make sure you are connected to the internet and not behind a proxy.", "ERROR", MessageBoxButton.OK);
                this.NavigationService.GoBack();
            }
        }

        void postcode_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            try
            {
                XDocument _doc = XDocument.Parse(e.Result);

                bool readLong = false;
                bool readLat = false;
                bool readName = false;
                foreach (XNode node in _doc.DescendantNodes())
                {
                    if (readLat)
                        lat = Convert.ToSingle(node.ToString());
                    if (readLong)
                        lon = Convert.ToSingle(node.ToString());
                    if (readName)
                        address = node.ToString();

                    readLong = false;
                    readLat = false;
                    readName = false;

                    if (node.ToString().StartsWith("<Name"))
                        readName = true;

                    if (node.ToString().StartsWith("<Latitude"))
                        readLat = true;

                    if (node.ToString().StartsWith("<Longitude"))
                        readLong = true;
                }

                pivotTitle.Title = address.ToUpper().Replace(", ", " - ");

                WebClient wClient = new WebClient();
                wClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(areaID_DownloadStringCompleted);
                wClient.DownloadStringAsync(new Uri("http://neighbourhood.statistics.gov.uk/NDE2/Disco/FindAreas?Postcode=" + postcode.Replace(" ", "").ToUpper(), UriKind.Absolute));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Can't read location data, please make sure you are connected to the internet and not behind a proxy.", "ERROR", MessageBoxButton.OK);
                this.NavigationService.GoBack();
            }
        }

        public class educationFormat
        {
            public string edubase_entry_id { get; set; }
            public string updated_at { get; set; }
            public string Latitude { get; set; }

                public class establishment_location_metadata
                {
                    public string grade { get; set; }
                    public string number_of_pupils { get; set; }
                    public string establishment_size { get; set; }
                    public string sector { get; set; }
                }

            public string id { get; set; }

                public class establishment
                {
                    public string establishment_name { get; set; }

                    public class cached_category_scores
                    {
                        public string happiness { get; set; }
                        public string exams { get; set; }
                    }
                }

            public string Longitude { get; set; }
            public string created_at { get; set; }
        }

        public class lifeRating
        {
            public string male { get; set; }
            public string female { get; set; }
        }

        public class lifeOverview
        {
            public string residents { get; set; }
            public string average_age { get; set; }
            public string dwellings { get; set; }
        }

        private void btnMap_Click(object sender, EventArgs e)
        {
            NavigationService.Navigate(new Uri("/Searcher/mapView.xaml?postcode=" + postcode + "&lat=" + lat + "&lon=" + lon, UriKind.Relative));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            NavigationService.Navigate(new Uri("/Searcher/mapView.xaml?postcode=" + postcode + "&lat=" + lat + "&lon=" + lon + "&edu=1", UriKind.Relative));
        }

        private void btnPin_Click(object sender, EventArgs e)
        {
            // Create the tile object and set some initial properties for the tile.
            // The Count value of 12 will show the number 12 on the front of the Tile. Valid values are 1-99.
            // A Count value of 0 will indicate that the Count should not be displayed.
            StandardTileData NewTileData = new StandardTileData
            {
                BackgroundImage = new Uri("ApplicationIcon.png", UriKind.Relative),
                Title = "Lifestyle - " + postcode,
                // Count = 12,
                BackTitle = postcode.ToUpper(),
                BackContent = address.Replace(", ", " - ").ToUpper().Replace(postcode.ToUpper() + " - ", ""),
                // BackBackgroundImage = new Uri("Blue.jpg", UriKind.Relative)
            };
            MessageBox.Show("Tile has been Pinned", "Tile Created", MessageBoxButton.OK);
            try
            {
                // Create the tile and pin it to Start. This will cause a navigation to Start and a deactivation of our application.
                ShellTile.Create(new Uri("/Searcher/Index.xaml?postcode=" + postcode.ToLower().Replace(" ", ""), UriKind.Relative), NewTileData);
            }
            catch { MessageBox.Show("You have already pinned this postcode to your Start screen.", "Tile Already Created", MessageBoxButton.OK); }
        }

        private void createRecent()
        {
            string[] recentOld = null;
            settings.TryGetValue<string[]>("recentValues", out recentOld);
            settings.Remove("recentValues");

            string[] recentNew = new string[5];
            recentNew[4] = recentOld[3];
            recentNew[3] = recentOld[2];
            recentNew[2] = recentOld[1];
            recentNew[1] = recentOld[0];
            recentNew[0] = postcode + "&" + address.Replace(postcode.ToUpper() + ", ", "");

            settings.Add("recentValues", recentNew);
            settings.Save();
        }

        private void btnFav_Click(object sender, EventArgs e)
        {
            string[] recentOld = null;
            settings.TryGetValue<string[]>("favs", out recentOld);
            settings.Remove("favs");

            bool cont = true;
            foreach (string line in recentOld)
            {
                if (line != null && line.ToLower().Contains(postcode.ToLower()))
                    cont = false;
            }

            if (cont)
            {
                string[] recentNew = new string[5];
                recentNew[4] = recentOld[3];
                recentNew[3] = recentOld[2];
                recentNew[2] = recentOld[1];
                recentNew[1] = recentOld[0];
                recentNew[0] = postcode + "&" + address.Replace(postcode.ToUpper() + ", ", "");

                settings.Add("favs", recentNew);
                settings.Save();
            }
            else
                MessageBox.Show("This postcode is already in your favorites", "ERROR", MessageBoxButton.OK);
        }
    }
}